package cc.shacocloud.kotlin.tools.uitls

import java.io.Serializable

/**
 * 将给定的 [Map] 适应 [MultiValueMap] 协定
 *
 * @see LinkedMultiValueMap\
 * @author 思追(shaco)
 */
open class MultiValueMapAdapter<K, V>(
    private val targetMap: MutableMap<K, MutableList<V>>,
) : MultiValueMap<K, V>, Serializable {

    override val size: Int get() = targetMap.size
    override val entries: MutableSet<MutableMap.MutableEntry<K, MutableList<V>>> get() = targetMap.entries
    override val keys: MutableSet<K> get() = targetMap.keys
    override val values: MutableCollection<MutableList<V>> get() = targetMap.values

    override fun getFirst(key: K): V? {
        val values = targetMap[key]
        return if (!values.isNullOrEmpty()) values[0] else null
    }

    override fun add(key: K, value: V) {
        val values = targetMap.computeIfAbsent(key) { arrayListOf() }
        values.add(value)
    }

    override fun addAll(key: K, values: List<V>) {
        val currentValues = targetMap.computeIfAbsent(key) { arrayListOf() }
        currentValues.addAll(values)
    }

    override fun addAll(values: MultiValueMap<K, V>) {
        for (entry in values.entries) {
            addAll(entry.key, entry.value)
        }
    }

    override fun set(key: K, value: V) {
        targetMap[key] = arrayListOf(value)
    }

    override fun setAll(values: Map<K, V>) {
        values.forEach { (key, value) -> this.set(key, value) }
    }

    override fun toSingleValueMap(): Map<K, V> {
        val singleValueMap: MutableMap<K, V> = LinkedHashMap(targetMap.size, 1f)
        targetMap.forEach { (key, values) ->
            if (values.isNotEmpty()) {
                singleValueMap[key] = values[0]
            }
        }
        return singleValueMap
    }


    override fun isEmpty(): Boolean {
        return targetMap.isEmpty()
    }

    override fun remove(key: K): MutableList<V>? {
        return targetMap.remove(key)
    }

    override fun put(key: K, value: MutableList<V>): MutableList<V>? {
        return targetMap.put(key, value)
    }


    override fun putAll(from: Map<out K, MutableList<V>>) {
        targetMap.putAll(from)
    }

    override fun clear() {
        targetMap.clear()
    }

    override fun containsValue(value: MutableList<V>): Boolean {
        return targetMap.containsValue(value)
    }

    override fun containsKey(key: K): Boolean {
        return targetMap.containsKey(key)
    }

    override fun get(key: K): MutableList<V>? {
        return targetMap.get(key)
    }

    override fun toString(): String {
        return targetMap.toString()
    }


    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (other !is MultiValueMapAdapter<*, *>) return false

        if (targetMap != other.targetMap) return false

        return true
    }

    override fun hashCode(): Int {
        return targetMap.hashCode()
    }
}
